package com.demo.function.orika;

import dev.akkinoc.spring.boot.orika.OrikaMapperFactoryConfigurer;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.converter.BidirectionalConverter;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.metadata.Type;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Configuration;

import java.time.*;
import java.util.Date;

/**
 * orika类型转换配置
 */
@Configuration
public class OrikaConfiguration implements OrikaMapperFactoryConfigurer {

    @Override
    public void configure(@NotNull MapperFactory orikaMapperFactory) {
        ConverterFactory converterFactory = orikaMapperFactory.getConverterFactory();
        converterFactory.registerConverter(new OrikaLocalDateTimeConverter());
        converterFactory.registerConverter(new OrikaLocalDateConverter());
    }

    /**
     * LocalDateTime与Date类型互转
     */
    public static class OrikaLocalDateTimeConverter extends BidirectionalConverter<Date, LocalDateTime> {

        @Override
        public LocalDateTime convertTo(Date source, Type<LocalDateTime> destinationType, MappingContext mappingContext) {
            return source.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        }

        @Override
        public Date convertFrom(LocalDateTime source, Type<Date> destinationType, MappingContext mappingContext) {
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zdt = source.atZone(zoneId);
            return Date.from(zdt.toInstant());
        }

    }

    /**
     * LocalDate与Date类型互转
     */
    public static class OrikaLocalDateConverter extends BidirectionalConverter<Date, LocalDate> {

        @Override
        public LocalDate convertTo(Date source, Type<LocalDate> destinationType, MappingContext mappingContext) {
            return source.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }

        @Override
        public Date convertFrom(LocalDate source, Type<Date> destinationType, MappingContext mappingContext) {
            Instant instant = source.atStartOfDay(ZoneId.systemDefault()).toInstant();
            return Date.from(instant);
        }

    }
}
